/*
 * Copyright 2007 Peter Zelenay.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *     
*/
package net.zelenay.jcrviewer;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.util.Properties;

import javax.swing.JFrame;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 
 * @author Peter Zelenay
 * 
 */
public final class Bootstrap {

	/**
	 * Path to the default property file containing application properties.
	 */
	public static final String DEFAULT_PROP_FILE = "/application.properties";
	
	/**
	 * Property containig path to application context.
	 */
	public static final String PROPS_APPCONTEXT = "applicationContext";

	/**
	 * Property containing name of bean for the main frame.
	 */
	public static final String PROPS_MAIN_FRAME = "mainFrameBean";

	/**
	 * Default log.
	 */
	private static final Log LOG = LogFactory.getLog(Bootstrap.class);

	/**
	 * Default properties used when application.properties not found.
	 */
	private static final Properties DEFAULT_PROPERTIES = new Properties();

	// initialize properties
	static {
		DEFAULT_PROPERTIES.setProperty(PROPS_APPCONTEXT,
				"classpath:/application.xml");
		DEFAULT_PROPERTIES.setProperty(PROPS_MAIN_FRAME, "mainFrame");
	}

	/**
	 * Properties used for this Bootstrap object.
	 */
	private final Properties properties = new Properties();

	/**
	 * Root application context.
	 */
	private ConfigurableApplicationContext ctx = null;

	/**
	 * Listener to correctly handle main frame window closes.
	 */
	private WindowListener listener = new WindowAdapter() {

		@Override
		public void windowClosing(final WindowEvent e) {
			shutDown();
			System.exit(0);
		}

	};
	
	/**
	 * Default constructor
	 * Uses DEFAULT_PROP_FILE as a property file path.
	 *
	 */
	public Bootstrap() {
		this(DEFAULT_PROP_FILE);
	}
	
	/**
	 * Create bootstrap reading properties from propFile.
	 * 
	 * @param propFile path to the property file to use
	 */
	public Bootstrap(final String propFile) {		
		loadProperties(propFile);
		initContext();
	}

	/**
	 * Close the context.
	 *
	 */
	public void shutDown() {
		if (ctx != null) {
			ctx.close();
		}
	}

	/** Locate the main frame in app context.
	 * 
	 * @return main frame of the app
	 */
	public JFrame getMainFrame() {
		String beanName = properties.getProperty(PROPS_MAIN_FRAME);
		JFrame fr = (JFrame) ctx.getBean(beanName);
		fr.addWindowListener(listener);
		return fr;
	}

	/**
	 * Load non default properties from.
	 * @param propFile path to the property file to read
	 */
	private void loadProperties(final String propFile) {
		// load defaults
		properties.putAll(DEFAULT_PROPERTIES);
		try {
			LOG.debug("Reading propery file:" + propFile);
			properties.load(Bootstrap.class
					.getResourceAsStream(propFile));
		} catch (IOException e) {
			LOG.warn("Unable to load application properties from application.properties file",e);
			LOG.warn("Using defaults");
		}
		if (LOG.isDebugEnabled()) {
			LOG.debug("Using following properties:" + properties);
		}
	}

	/**
	 * Initialize application context.
	 *
	 */
	private void initContext() {
		String ctxPath = properties.getProperty(PROPS_APPCONTEXT);
		LOG.debug("Initializing application context: " + ctxPath);
		ctx = new ClassPathXmlApplicationContext(ctxPath);
	}
}
